/***************************************************************************
 *   Copyright (C) 2007 by Warren Kenny   				   *
 *   warren.kenny@gmail.com   						   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef GSDATAPACKER_H
#define GSDATAPACKER_H

#include <gsystems/gsCore.h>

class gsDataPacker
{
public:
	gsDataPacker();
	
	
	/**
	 * Packs a primitive object into the specified buffer
	 * @param[in] dataBuffer The buffer into which the object should be packed
	 * @param[in] bufferSize The size of the destination buffer
	 * @param[in] offset The offset into the destination buffer where writing should begin
	 * @param[out] newOffset The new offset produced by packing the object after the offset point
	 * @param[in] variable The object to be packed into the buffer
	 * @return 	- True if the object was packed successfully
	 *		- False otherwise
	 */
	template<class T>
	static gsBool pack( 	char *dataBuffer, 
				const unsigned int bufferSize, 
				const unsigned int offset, 
				unsigned int &newOffset, 
				const T& variable )
	{
		return appendToBuffer( dataBuffer, bufferSize, offset, newOffset, &variable, sizeof(variable) );
	}
	
	
	/**
	 * Removes a primitive object from the specified buffer
	 * @param[in] dataBuffer The buffer from which the object should be removed
	 * @param[in] bufferSize The size of the source buffer
	 * @param[in] offset The offset into the source buffer where removal should begin
	 * @param[out] newOffset The new offset produced after removing the object after the offset point
	 * @param[out] variable A reference to the object to be removed
	 * @return 	- True if the object was removed successfully
	 *		- False otherwise
	 */
	template<class T>
	static gsBool remove( 	const char *dataBuffer, 
				const unsigned int bufferSize, 
				const unsigned int offset, 
				unsigned int &newOffset, 
				T& variable )
	{
		return removeFromBuffer( dataBuffer, bufferSize, offset, newOffset, &variable, sizeof(variable) );
	}
	
	
	/**
	 * Safely copies data from one buffer into another
	 * @param destination The destination buffer
	 * @param destinationSize The size of the destination buffer
	 * @param offset The offset into the destination buffer where copying should begin from
	 * @param newOffset The new offset into the destination buffer produced by copying from the offset point
	 * @param source The source buffer where data should be copied from
	 * @param sourceSize The amount of data to be copied from the source buffer
	 * @return 	- True if the copy was successful
	 *		- False otherwise
	 */
	static gsBool bufferCopy( char *destination, 
				unsigned int destinationSize, 
    				const unsigned int offset, 
				unsigned int &newOffset, 
    				const void *source, 
				const unsigned int sourceSize ); 

	~gsDataPacker();
	
	
private:
	
	static gsBool appendToBuffer( 	char *dataBuffer, 
					const unsigned int bufferSize, 
					const unsigned int offset, 
					unsigned int &newOffset, 
					const void *const sourceBuffer, 
					const unsigned int sourceBufferSize );
	
	static gsBool removeFromBuffer( const char *dataBuffer, 
					const unsigned int bufferSize, 
					const unsigned int offset, 
					unsigned int &newOffset, 
					void *const destinationBuffer, 
					const unsigned int destinationBufferSize );
};

#endif
